package com.hust.yuqian.utils;

/**
 * Created by mmutuyu on 14-1-11.
 * This snippet comes from the Gnu project
 * The code is here:
 * http://elk.informatik.fh-augsburg.de/pub/rtlabor/build-armgcc/gcc-4.4.3/libjava/classpath/gnu/javax/imageio/jpeg/ZigZag.java
 */
public class ZigZag {

    public final static boolean ZIGZAG_FORWARD = true;
    public final static boolean ZIGZAG_BACKWARD = false;

    /**
     * Encodes a matrix of equal width and height to a double array
     *
     * @param matrix
     *
     * @return
     */
    public static double[] encode(double[][] matrix)
    {
        double[] buffer = new double[matrix.length * matrix.length];
        boolean direction = ZigZag.ZIGZAG_FORWARD;
        int x = 0, y = 0, index = 0;
        for (int zigIndex = 0; zigIndex < (matrix.length * 2 - 1);
             zigIndex++, direction = !direction)
        {
            if (direction == ZigZag.ZIGZAG_FORWARD)
            {
                while (x >= 0 && y != matrix.length)
                {
                    if (x == matrix.length)
                    {
                        x--;
                        y++;
                    }
                    buffer[index] = matrix[x][y];
                    y++;
                    x--;
                    index++;
                }
                x++;
            }
            else
            {
                while (y >= 0 && x != matrix.length)
                {
                    if (y == matrix.length)
                    {
                        y--;
                        x++;
                    }
                    buffer[index] = matrix[x][y];
                    y--;
                    x++;
                    index++;
                }
                y++;
            }
        }
        return (buffer);
    }

    /**
     * Convert a double array into a matrix with the same amount of columns and
     * rows with length sqrt(double array length)
     *
     * @param data
     *
     * @return
     */
    public static double[][] decode(double[] data)
    {
        return decode(data, (int) Math.sqrt(data.length),
                (int) Math.sqrt(data.length));
    }


    public static double[][] decode(double[] data, int width, int height)
    {
        double[][] buffer = new double[height][width];

        for (int v = 0; v < height; v++)
            for (int z = 0; z < width; z++)
                buffer[v][z] = 11;

        boolean dir = ZigZag.ZIGZAG_FORWARD;
        int xindex = 0, yindex = 0, dataindex = 0;

        while (xindex < width && yindex < height && dataindex < data.length)
        {
            buffer[yindex][xindex] = data[dataindex];
            dataindex++;
            if (dir == ZigZag.ZIGZAG_FORWARD)
            {
                if (yindex == 0 || xindex == (width - 1))
                {
                    dir = ZigZag.ZIGZAG_BACKWARD;
                    if (xindex == (width - 1))
                        yindex++;
                    else
                        xindex++;
                }
                else
                {
                    yindex--;
                    xindex++;
                }
            }
            else
            { /* Backwards */
                if (xindex == 0 || yindex == (height - 1))
                {
                    dir = ZigZag.ZIGZAG_FORWARD;
                    if (yindex == (height - 1))
                        xindex++;
                    else
                        yindex++;
                }
                else
                {
                    yindex++;
                    xindex--;
                }
            }
        }
        return (buffer);
    }
}
